package com.hzw.saas.service.rss.service;

import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import javax.annotation.Resource;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzw.saas.api.rss.*;
import com.hzw.saas.api.rss.bo.*;
import com.hzw.saas.common.util.MapperUtil;
import com.hzw.saas.common.util.SnowFlakeUtil;
import com.hzw.saas.service.rss.mapper.JournalUserActionMapper;
import com.hzw.saas.service.rss.model.Journal;
import com.hzw.saas.service.rss.model.JournalUserAction;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 期刊相关的用户记录 服务实现类
 * </p>
 *
 * @author sonam
 * @since 2021-06-30
 */
@Service("journalUserActionService")
public class JournalUserActionServiceImpl extends ServiceImpl<JournalUserActionMapper, JournalUserAction> implements IJournalUserActionService, IService<JournalUserAction> {

    @Resource(name = "journalArticleService")
    private IJournalArticleService journalArticleService;
    @Resource(name = "journalCatalogUserService")
    private IJournalCatalogUserService journalCatalogUserService;
    @Resource(name = "journalCustomService")
    private IJournalCustomService journalCustomService;
    @Resource(name = "journalUserAxisService")
    private IJournalUserAxisService journalUserAxisService;
    @Resource(name = "journalService")
    private IJournalService journalService;
    @Autowired
    private JournalUserActionMapper journalUserActionMapper;

    private static  final ExecutorService exec = Executors.newSingleThreadExecutor();
    @Override
    public JournalUserActionBO getById(String pid) {
        if(StrUtil.isBlank(pid)) return null;
        return MapperUtil.nf().map(super.getById(pid), JournalUserActionBO.class);
    }

    @Override
    public List<JournalUserActionBO> query(JournalUserActionBO journalUserActionBO) {
        if(Objects.isNull(journalUserActionBO)) return MapperUtil.nf().mapAsList(this.list(), JournalUserActionBO.class);
        JournalUserAction journalUserAction = MapperUtil.nf().map(journalUserActionBO, JournalUserAction.class);
        List<JournalUserAction> userActions = this.list(Wrappers.<JournalUserAction>query().setEntity(journalUserAction));
        return MapperUtil.nf().mapAsList(userActions, JournalUserActionBO.class);
    }

    @Override
    public JournalUserActionBO getOne(JournalUserActionBO journalUserActionBO) {
        List<JournalUserActionBO> query = query(journalUserActionBO);
        if(CollectionUtil.isEmpty(query)) {
            return null;
        }
        return query.get(0);
    }

    @Override
    public void update(JournalUserActionBO journalUserActionBO) {
        if(journalUserActionBO == null) return;
        JournalUserAction journalUserAction = MapperUtil.nf().map(journalUserActionBO, JournalUserAction.class);
        this.updateById(journalUserAction);
    }

    @Override
    public void delete(JournalUserActionBO journalUserActionBO) {
        if(journalUserActionBO == null) return;
        this.remove(Wrappers.<JournalUserAction>query().setEntity(MapperUtil.nf().map(journalUserActionBO, JournalUserAction.class)));
    }

    @Override
    public void delete(String pid) {
        if(StrUtil.isBlank(pid)) return;
        this.removeById(pid);
    }

    @Override
    public List<JournalUserActionBO> findFavJournalUserActionByUserId(String userId){
        List<JournalUserAction> list = this.lambdaQuery().eq(JournalUserAction::getUserId, userId)
            .eq(JournalUserAction::getIsDelete, 0)
            .eq(JournalUserAction::getIsFav,1).list();
        if (CollectionUtil.isNotEmpty(list)){
            return MapperUtil.nf().mapAsList(list,JournalUserActionBO.class);
        }
        return null;
    }

    @Override
    public List<JournalUserActionBO> findAllJournalUserActionByUserId(String userId) {
        List<JournalUserAction> list = this.lambdaQuery().eq(JournalUserAction::getUserId, userId)
            .list();
        if (CollectionUtil.isNotEmpty(list)){
            return MapperUtil.nf().mapAsList(list,JournalUserActionBO.class);
        }
        return null;
    }

    @Override
    public void saveBatch(List<JournalUserActionBO> journalUserActionBOS) {
        journalUserActionBOS.forEach(journalArticleBO -> {
            journalArticleBO.setPid(SnowFlakeUtil.nextIdStr());
        });
        saveBatch(MapperUtil.nf().mapAsList(journalUserActionBOS, JournalUserAction.class));
    }

    @Override
    public void updateBatch(List<JournalUserActionBO> journalArticleBOS) {

        updateBatchById(MapperUtil.nf().mapAsList(journalArticleBOS,JournalUserAction.class));
    }

    @Override
    public Integer journalArticleIsFav(String articleId, String userId) {
        return this.count(Wrappers.<JournalUserAction>lambdaQuery()
            .eq(JournalUserAction::getArticleId, articleId)
            .eq(JournalUserAction::getUserId, userId)
            .eq(JournalUserAction::getIsFav, 1)) > 0 ? 1 : 0;
    }

    @Override
    public Integer changeReadStatus(String articleId, String userId) {
        List<JournalUserAction> list = this.lambdaQuery()
            .eq(JournalUserAction::getArticleId, articleId)
            .eq(JournalUserAction::getUserId, userId)
            .list();
        if (CollectionUtil.isEmpty(list)){
            JournalUserAction journalUserAction = new JournalUserAction();
            journalUserAction.setUserId(userId);
            journalUserAction.setReadStatus(1);
            journalUserAction.setArticleId(articleId);
            journalUserAction.setReadDate(new Date());
            journalUserAction.setPid(SnowFlakeUtil.nextIdStr());
            this.save(journalUserAction);
        }else {
            JournalUserAction journalUserAction = list.get(0);
            journalUserAction.setReadStatus(1);
            journalUserAction.setReadDate(new Date());
            JournalUserActionBO map = MapperUtil.nf().map(journalUserAction, JournalUserActionBO.class);
            update(map);
        }
        //查询当前站点剩余未读
        JournalArticleBO byId = journalArticleService.getById(articleId);
        if (byId != null){
            String rssId = byId.getRssId();
            ArrayList<String> strings = new ArrayList<>();
            strings.add(rssId);
            List<JournalCustomBO> byUserAndRssId = journalCustomService.findByUserAndRssId(userId, strings);
            if (CollectionUtil.isNotEmpty(byUserAndRssId)){
                List<String> collect = byUserAndRssId.stream().filter(o->o.getReadTime().before(new Date())).map(JournalCustomBO::getPid).collect(Collectors.toList());
                List<JournalUserAxisBO> unRead = journalUserAxisService.findUnRead(userId, collect);
                Map<String, Integer> unRead1 = findUnRead(byUserAndRssId, userId,unRead);
                return unRead1.get(rssId);
            }

        }
        return 0;
    }

    @Override
    public Map<String,Integer> findUnRead(List<JournalCustomBO> journalCustomBOS, String userId, List<JournalUserAxisBO> userAxisBOS) {
        List<JournalUserAxisBO> collect1 = userAxisBOS.stream().filter(o -> o.getAxisStatus().equals(1)).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(journalCustomBOS)) {
            List<String> rssIds = journalCustomBOS.stream().map(JournalCustomBO::getJournalId).collect(Collectors.toList());
            //查询分页的所有文章
            List<JournalArticleBO> journalArticleByJournalIds = journalArticleService.findJournalArticleByJournalIds(rssIds);

            //查询用户的所有已读文章
            List<JournalUserAction> list = this.lambdaQuery().eq(JournalUserAction::getUserId, userId)
                .eq(JournalUserAction::getIsDelete, 0)
                .list();

            HashMap<String, Integer> stringIntegerHashMap = new HashMap<>();
            if (CollectionUtil.isNotEmpty(journalArticleByJournalIds)) {
                //查询出所有站点上一次这次事件的开始时间
                ArrayList<JournalArticleBO> journalArticleBOArrayList = new ArrayList<>();
                if (CollectionUtil.isNotEmpty(collect1)) {
                    HashMap<String, Date> stringDateHashMap = new HashMap<>();
                    journalCustomBOS.forEach(journalCustomBO -> {
                        collect1.forEach(journalUserAxisBO -> {
                            if (journalCustomBO.getPid().equals(journalUserAxisBO.getJournalId())) {
                                stringDateHashMap.put(journalCustomBO.getJournalId(), journalUserAxisBO.getCreateTime());
                            }
                        });
                    });
                    journalArticleByJournalIds.forEach(journalArticleBO -> {
                        stringDateHashMap.forEach((s, d) -> {
                            if (journalArticleBO.getRssId().equals(s) && journalArticleBO.getCreateTime().before(d)) {
                                journalArticleBOArrayList.add(journalArticleBO);
                            }
                        });
                    });
                    journalArticleByJournalIds.removeAll(journalArticleBOArrayList);
                }
                    if (CollectionUtil.isNotEmpty(list)) {
                        ArrayList<JournalArticleBO> journalArticleBOS = new ArrayList<>();
                        journalArticleByJournalIds.forEach(journalArticleBO -> {
                            list.forEach(journalUserAction -> {
                                if (journalArticleBO.getPid().equals(journalUserAction.getArticleId())) {
                                    journalArticleBOS.add(journalArticleBO);
                                }
                            });
                        });
                        journalArticleByJournalIds.removeAll(journalArticleBOS);

                }

                    Map<String, List<JournalArticleBO>> collect = journalArticleByJournalIds.stream().collect(Collectors.groupingBy(JournalArticleBO::getRssId));
                    collect.forEach((s, journalArticleBOs) -> {
                        stringIntegerHashMap.put(s, journalArticleBOs.size());
                    });
                    return stringIntegerHashMap;
            }
            return new HashMap<>();
        }
        return new HashMap<>();
    }

    @SneakyThrows
    @Override
    public Integer setAllRead(String userId, List<String> journalId) {
        ArrayList<String> strings = new ArrayList<>();
        if(CollectionUtil.isEmpty(journalId)){
            List<JournalCatalogUserBO> catalogTreeByUserId = journalCatalogUserService.getCatalogTreeByUserId(userId);
            if (CollectionUtil.isNotEmpty(catalogTreeByUserId)){
                ArrayList<JournalCatalogUserBO> journalCatalogUserBOS = new ArrayList<>();
                catalogTreeByUserId.forEach(journalCatalogUserBO -> {
                    List<JournalCatalogUserBO> journalCatalogUserBOS1 = journalCatalogUserBO.getJournalCatalogUserBOS();
                    if (CollectionUtil.isNotEmpty(journalCatalogUserBOS1)){
                        journalCatalogUserBOS.addAll(journalCatalogUserBOS1);
                    }
                });
                List<String> collect = journalCatalogUserBOS.stream().map(JournalCatalogUserBO::getCatalogId).collect(Collectors.toList());
                strings.addAll(collect);
            }
        }else {
            strings.addAll(journalId);
        }
        if (CollectionUtil.isNotEmpty(strings)){
            List<JournalBO> byCatalogIds = journalCustomService.findByPIds(strings);
            ArrayList<JournalUserActionBO> journalUserActionBOS = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(byCatalogIds)){
                List<String> collect = byCatalogIds.stream().map(JournalBO::getPid).collect(Collectors.toList());
                //查询用户所有的订阅文章所有的文章
                List<JournalArticleBO> journalArticleByJournalIds = journalArticleService.findJournalArticleByJournalIds(collect);
                //用户所有已读文章
                List<JournalUserAction> list = this.lambdaQuery().eq(JournalUserAction::getUserId, userId)
                    .eq(JournalUserAction::getIsDelete, 0)
                    .list();
                ArrayList<JournalArticleBO> journalArticleBOS = new ArrayList<>();
                if (CollectionUtil.isNotEmpty(list)){
                    List<String> collect1 = list.stream().map(JournalUserAction::getArticleId).collect(Collectors.toList());
                    if (CollectionUtil.isNotEmpty(journalArticleByJournalIds)){
                        journalArticleByJournalIds.forEach(journalArticleBO -> {
                            collect1.forEach(s -> {
                                if (journalArticleBO.getPid().equals(s)){
                                    journalArticleBOS.add(journalArticleBO);
                                }
                            });
                        });
                        //去除所有已经阅读和收藏的文章
                        journalArticleByJournalIds.removeAll(journalArticleBOS);
                    }
                }
                journalArticleByJournalIds.forEach(journalArticleBO -> {
                    JournalUserActionBO journalUserActionBO = new JournalUserActionBO();
                    journalUserActionBO.setUserId(userId);
                    journalUserActionBO.setReadStatus(1);
                    journalUserActionBO.setReadDate(new Date());
                    journalUserActionBO.setArticleId(journalArticleBO.getPid());
                    journalUserActionBOS.add(journalUserActionBO);
                });

            }

            if (CollectionUtil.isNotEmpty(journalUserActionBOS)){
                saveByExecutor(journalUserActionBOS);
            }
        }
        return 0 ;
    }

    @Override
    public List<JournalUserActionBO> findByUserAndArticleIds(List<String> ids, String userId) {
        if(CollectionUtil.isNotEmpty(ids)){
            List<JournalUserAction> list = this.lambdaQuery().eq(JournalUserAction::getUserId, userId)
                .in(JournalUserAction::getArticleId, ids)
                .list();
            return MapperUtil.nt().mapAsList(list,JournalUserActionBO.class);
        }

        return Collections.emptyList();
    }

    @Override
    public List<String> findByUserAndRssId(String pid, String userId) {
        JournalCustomBO byId = journalCustomService.findById(pid);
        if (byId != null){
            JournalBO byId1 = journalService.getById(byId.getJournalId());
            ArrayList<String> strings = new ArrayList<>();
            strings.add(byId1.getPid());
            List<JournalArticleBO> byJournalIds = journalArticleService.findByJournalIds(strings);
            if (CollectionUtil.isNotEmpty(byJournalIds)){
                List<String> collect = byJournalIds.stream().map(JournalArticleBO::getPid).collect(Collectors.toList());
                List<JournalUserAction> list = this.lambdaQuery().eq(JournalUserAction::getUserId, userId).in(JournalUserAction::getArticleId, collect)
                    .list();
                if (CollectionUtil.isNotEmpty(list)){
                    return list.stream().map(JournalUserAction::getPid).collect(Collectors.toList());
                }
            }


        }
        return Collections.emptyList();
    }

    @Override
    public void deleteBatchByIds(List<String> pids) {
        journalUserActionMapper.deleteByCatalogIdsFromSql(pids);
    }

    @Override
    public void deleteByUserAndJournalIdS(String userId, List<String> pids) {
        if (CollectionUtil.isEmpty(pids)||StrUtil.isBlank(userId)){
            return;
        }
        List<JournalArticleBO> byJournalIds = journalArticleService.findByJournalIds(pids);
        if (CollectionUtil.isNotEmpty(byJournalIds)){
            List<String> collect = byJournalIds.stream().map(JournalArticleBO::getPid).collect(Collectors.toList());
            List<JournalUserAction> list = this.lambdaQuery().in(JournalUserAction::getArticleId, collect)
                .eq(JournalUserAction::getIsFav,0)
                .eq(JournalUserAction::getUserId, userId)
                .list();
            if (CollectionUtil.isNotEmpty(list)){
                List<String> actionIds = list.stream().map(JournalUserAction::getPid).collect(Collectors.toList());
                this.removeByIds(actionIds);
            }
        }

    }


    public void saveByExecutor(List<JournalUserActionBO> journalUserActionBOS){
        exec.execute(new Runnable() {
            public void run() {
                saveBatch(journalUserActionBOS);
            }
        });
        exec.shutdown();
        return;
    }
}

